#include "../libxluploader.h"

class IAnonymousSite : public ISite {
	virtual std::string parseImageUrl (const std::string &response) = 0;
	virtual std::string getUrl() const = 0;
	virtual void postGet(std::string &html) {} // give siteXXX a chance to modify the html
	virtual void prePost(const std::string &html, const HtmlDom &dom, std::string &cookie) const {}
public:
	// your need to implement:
	// virtual TCHAR* getSiteName () = 0;
	// parseImageUrl()
	// getUrl()

	virtual HttpCode uploadFile (
	                             std::string &imageurl_or_response,
	                             const TCHAR *fileName,
	                             HttpProgressCallback progressCb,
	                             void *progressParam
	                            ) {
		std::string url = getUrl();
		std::string response;
		std::string cookie;
#if 0 // if use http_upload, I can't make call of prePost() in it.
		HttpCode res = http_upload(response, url, fileName, cookie, progressCb, progressParam);
#else
		// 1. get html
		std::string html;
		CURLcode res = http_get(html, url.c_str(), cookie, progressCb, progressParam);
		if (res != CURLE_OK) {
			return res;
		}

		// 2. postGet, give derived class a chance to modify the html
		postGet(html);

		// 3. get dom
		HtmlDom dom = html_load(html);

		// 4. get the form & inputs
		HtmlNodeIterArray::iterator it;
		HtmlNodeIterArray forms = html_get_nodes_by_tag(dom, "form");
		HtmlNodeIterArray inputs;
		HtmlNodeIter itForm;
		for (it = forms.begin(); it != forms.end(); ++ it) {
			inputs = html_get_children(dom, *it, "input");
			HtmlNodeIterArray::iterator itInput;
			for (itInput = inputs.begin(); itInput != inputs.end(); ++ itInput) {
				(*itInput)->parseAttributes();
				if (_stricmp((*itInput)->attribute("type").second.c_str(), "file") == 0) {
					break;
				}
			}
			if (itInput != inputs.end()) {
				// found the form
				itForm = *it;
				break;
			}
		}
		if (it == forms.end()) {
			return CURLE_REMOTE_FILE_NOT_FOUND; // no form found
		}

		// 5. get post url
		itForm->parseAttributes();
		std::string post_url = itForm->attribute("action").second;
		post_url = util_get_form_action_url(url, post_url);

		// 6. pre-post
		prePost(html, dom, cookie);

		// 7. post
		std::string referer = url;
		res = http_post(response, post_url, inputs, fileName, cookie, progressCb, progressParam, referer);

#endif
		if (res == CURLE_OK) {
			imageurl_or_response = parseImageUrl(response);
			if (imageurl_or_response.length() == 0) {
				imageurl_or_response = response;
				res = ISite::PATTERN_NOT_FOUND;
			}
		}

		return res;
	}
};


//////////////////////////////////////////////////////////////////////////
// anonymous sites
class CSiteTinyPic : public IAnonymousSite {
	pcre *m_pcreCodePic;
	pcre *m_pcreCodeIval;
	pcre *m_pcreCodeType;
	const char *m_errPic;
	int m_errPicOffset;
	const char *m_errIval;
	int m_errIvalOffset;
	const char *m_errType;
	int m_errTypeOffset;
	virtual std::string parseImageUrl (const std::string &response);
	virtual std::string getUrl() const;
public:
	CSiteTinyPic();
	virtual ~CSiteTinyPic();
	virtual TCHAR* getSiteName();
};


class CSiteImgPlace : public IAnonymousSite {
	pcre *m_pcreCodePic;
	const char *m_errPic;
	int m_errPicOffset;
	virtual std::string parseImageUrl (const std::string &response);
	virtual std::string getUrl() const;
public:
	CSiteImgPlace();
	virtual ~CSiteImgPlace();
	virtual TCHAR* getSiteName();
};


class CSiteImageHostOrg : public IAnonymousSite {
	pcre *m_pcreCodePic;
	const char *m_errPic;
	int m_errPicOffset;
	virtual std::string parseImageUrl (const std::string &response);
	virtual std::string getUrl() const;
	virtual void prePost(const std::string &html, const HtmlDom &dom, std::string &cookie) const;
public:
	CSiteImageHostOrg();
	virtual ~CSiteImageHostOrg();
	virtual TCHAR* getSiteName();
};

class CSiteImgur : public IAnonymousSite {
	pcre *m_pcreCodePic;
	const char *m_errPic;
	int m_errPicOffset;
	virtual std::string parseImageUrl (const std::string &response);
	virtual std::string getUrl() const;
public:
	CSiteImgur();
	virtual ~CSiteImgur();
	virtual TCHAR* getSiteName();
};

class CSiteImageShack : public IAnonymousSite {
	pcre *m_pcreCodePic;
	const char *m_errPic;
	int m_errPicOffset;
	virtual std::string parseImageUrl (const std::string &response);
	virtual std::string getUrl() const;
public:
	CSiteImageShack();
	virtual ~CSiteImageShack();
	virtual TCHAR* getSiteName();
};
